package com.xb.loan.usercenter.account.impl;

import com.xb.loan.account.service.ILotCashService;
import com.xb.loan.account.service.bean.LotCashBillVO;
import com.xb.loan.account.service.bean.LotCashInfoVO;
import com.xb.loan.account.service.constant.AccountConst;
import com.xb.loan.account.service.exception.IAccountServiceException;
import com.xb.loan.log.exception.BizException;
import com.xb.loan.usercenter.account.common.VerifySet;
import com.xb.loan.usercenter.account.dao.LotCashBillDao;
import com.xb.loan.usercenter.account.dao.LotCashInfoDao;
import com.xb.loan.usercenter.account.dao.bean.LotCashBill;
import com.xb.loan.usercenter.account.dao.bean.LotCashInfo;
import com.xb.loan.usercenter.service.user.bean.UserInfoVO;
import com.xb.loan.util.SpringHelper;
import com.xb.loan.util.cache.redis.comm.FormatOperation;
import com.xb.loan.util.common.ObjectOperation;
import com.xb.loan.util.log.DefaultLoggerFacotry;
import com.xb.loan.util.log.LogFormatUtil;
import com.xb.loan.util.mybatis.MyTransactional;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 北京掌中彩信息科技有限公司源代码，版权归北京掌中彩信息科技有限公司所有。
 * 
 * 项目名称 : common-biz 创建日期 : 2015年9月9日 修改历史 : 1. [2015年9月9日]创建文件 by wenju.song
 */
@Service("lotCashService")
public class LotCashServiceImpl implements ILotCashService {
	private static Logger logger = DefaultLoggerFacotry.getLogger(LotCashServiceImpl.class);

	@Autowired
	private LotCashInfoDao lotCashInfoDao;

	@Autowired
	private LotCashBillDao lotCashBillDao;

	@Override
	public int createLotCash(LotCashInfoVO lotCashInfoVO) throws BizException {
		VerifySet.verifyLotCashInfoVO(lotCashInfoVO);
		
		LotCashInfo lotCashInfo = ObjectOperation.convertByClasses(lotCashInfoVO, LotCashInfo.class);
		
		return lotCashInfoDao.insert(lotCashInfo);
	}

	@Override
	public LotCashInfoVO queryLotCashInfoById(String accountId) throws BizException {
		LotCashInfoVO result = null;
		LotCashInfo lotCashInfo = lotCashInfoDao.queryLotCashInfoById(accountId);
		if (lotCashInfo == null)
			return result;
		result = ObjectOperation.convertByClasses(lotCashInfo, LotCashInfoVO.class);
		return result;
	}
	
	@Override
	public LotCashInfoVO queryLotCashInfoByUserId(String userId) throws BizException {
		VerifySet.verifyUserId(userId);
		
		LotCashInfoVO result = null;
		LotCashInfo lotCashInfo = lotCashInfoDao.queryLotCashInfoByUserId(userId);
		if (lotCashInfo == null)
			return result;
		result = ObjectOperation.convertByClasses(lotCashInfo, LotCashInfoVO.class);
		return result;
	}

	@Override
	public List<LotCashBillVO> queryLotCashBill(String userId, Integer feeType, Integer billType, String startDate, String endDate, int pageNum, int numPerPage) throws BizException {
		VerifySet.verifyUserId(userId);
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("feeType", feeType);
		params.put("billType", billType);
		params.put("startDate", startDate);
		params.put("endDate", endDate);
		params.put("pageNum", pageNum);
        params.put("numPerPage", numPerPage);

		List<LotCashBillVO> result = null;

		List<LotCashBill> lotCashBills = lotCashBillDao.queryLotCashBill(params);
		if (lotCashBills == null || lotCashBills.size() == 0)
			return result;
		result = ObjectOperation.convertByClassesList(lotCashBills, LotCashBillVO.class);
		return result;
	}

	@Override
	public int queryLotCashBillCount(String userId, Integer feeType, Integer billType, String startDate, String endDate) throws BizException {
		VerifySet.verifyUserId(userId);
		
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("feeType", feeType);
		params.put("billType", billType);
		params.put("startDate", startDate);
		params.put("endDate", endDate);

		return lotCashBillDao.queryLotCashBillCount(params);
	}

	@Override
	public int updateLotCashInfo(String accountId, String partnerId, Integer status) throws BizException {
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("accountId", accountId);
		params.put("partnerId", partnerId);
		params.put("status", status);	
		return lotCashInfoDao.updateLotCashInfo(params);
	}

	@Override
	public void addMoney(String foreignId, UserInfoVO userInfoVO, double money, int billType, String accountPeriod) throws BizException {
		//验证彩金和账户信息
		verifyMoney(money);
		VerifySet.verifyUserInfoVO(userInfoVO);
		LotCashInfo lotCashInfo = lotCashInfoDao.queryLotCashInfoById(userInfoVO.getAccountId());
		VerifySet.verifyLotCashInfoIsNormal(lotCashInfo);
		
		LotCashInfo lotCashInfoDelta = new LotCashInfo();
		lotCashInfoDelta.setAccountId(userInfoVO.getAccountId());
		lotCashInfoDelta.setMoney(money);

		LotCashBill lotCashBill = createLotCashBill(userInfoVO, billType, foreignId);
		lotCashBill.setBillIncome(money);

		LotCashServiceImpl self = SpringHelper.getBean("lotCashService");
		self.addMoneyTransaction(userInfoVO, lotCashInfoDelta, lotCashBill);
		logger.info(LogFormatUtil.getFormatMsg(new String[]{"module", "foreignId", "userId", "money", "billType"},
				new Object[] { "lotCash_add", foreignId, userInfoVO.getUserId(), money, billType}));
	}

	@MyTransactional
	public void addMoneyTransaction(UserInfoVO userInfo, LotCashInfo lotCashInfoDelta, LotCashBill lotCashBill) {
		// 获取账户余额
		LotCashInfo cashInfo = lotCashInfoDao.queryLotCashInfoById(userInfo.getAccountId());
		
		lotCashInfoDao.addMoney(lotCashInfoDelta);
		// 更新账户金额
		lotCashBill.setLastMoney(cashInfo.getMoney());
		// 更新账户余额
		lotCashBill.setCurMoney(cashInfo.getMoney() + lotCashInfoDelta.getMoney());

		lotCashBillDao.insert(lotCashBill);

	}

	@Override
	public void deductMoney(String foreignId, UserInfoVO userInfoVO, double money, int billType, String accountPeriod) throws BizException {
		//验证彩金和账户信息
		verifyMoney(money);
		VerifySet.verifyUserInfoVO(userInfoVO);
		LotCashInfo lotCashInfo = lotCashInfoDao.queryLotCashInfoById(userInfoVO.getAccountId());
		VerifySet.verifyLotCashInfoIsNormal(lotCashInfo);
		
		LotCashInfo lotCashInfoDelta = new LotCashInfo();
		lotCashInfoDelta.setAccountId(userInfoVO.getAccountId());
		lotCashInfoDelta.setMoney(money);

		LotCashBill lotCashBill = createLotCashBill(userInfoVO, billType, foreignId);
		lotCashBill.setBillExpend(money);

		LotCashServiceImpl self = SpringHelper.getBean("lotCashService");
		self.deductMoneyTransaction(userInfoVO, lotCashInfoDelta, lotCashBill);

		logger.info(LogFormatUtil.getFormatMsg(new String[]{"module", "foreignId", "userId", "money", "billType"},
				new Object[] { "lotcash_deduct", foreignId, userInfoVO.getUserId(), money, billType}));
	}

	@MyTransactional
	public void deductMoneyTransaction(UserInfoVO userInfo, LotCashInfo lotCashInfoDelta, LotCashBill lotCashBill) throws BizException {
		// 获取账户余额
		LotCashInfo cashInfo = lotCashInfoDao.queryLotCashInfoById(userInfo.getAccountId());
		int length = lotCashInfoDao.deductMoney(lotCashInfoDelta);
		if (length < 1)
			throw IAccountServiceException.noEnoughMoney;
		
		// 更新账户金额
		lotCashBill.setLastMoney(cashInfo.getMoney());
		// 更新账户余额
		lotCashBill.setCurMoney(cashInfo.getMoney() - lotCashInfoDelta.getMoney());

		lotCashBillDao.insert(lotCashBill);
	}

	private void verifyMoney(double money) throws BizException {
		if (money <= 0) {
			logger.warn(LogFormatUtil.getFormatMsg(new String[]{"module", "money", "msg"},
					new Object[]{"lotCash", money,  IAccountServiceException.moneyNotPositive.getMessage()}));
			throw IAccountServiceException.moneyNotPositive;
		}
	}

	private LotCashBill createLotCashBill(UserInfoVO userInfo, int billType, String foreignId) {
		LotCashBill lotCashBill = new LotCashBill();
		lotCashBill.setBillId(FormatOperation.assemblySeq(AccountConst.PriKey_Name, AccountConst.PriKey_Length));
		lotCashBill.setAccountId(userInfo.getAccountId());
		lotCashBill.setUserId(userInfo.getUserId());
		lotCashBill.setPartnerId(userInfo.getPartnerId());
		lotCashBill.setFeeType(AccountConst.FeeType_Default);
		lotCashBill.setBillType(billType);
		lotCashBill.setForeignId(foreignId);
		return lotCashBill;
	}

	@Override
	public void flushes(String userId, String foreignId, int billType) throws BizException {
		if(billType != AccountConst.BillType_Encash || billType != AccountConst.BillType_Purchase_Lottery){
			logger.error(LogFormatUtil.getFormatMsg(new String[]{"module", "foreignId", "billType", "msg"},
					new Object[]{"account", foreignId, billType, IAccountServiceException.invalidFlushesType.getMessage()}));
			throw IAccountServiceException.invalidFlushesType;
		}
		Map<String, Object> params = new HashMap<String, Object>();
		params.put("userId", userId);
		params.put("foreignId", foreignId);
		params.put("billType", billType);
		params.put("isFlushes", AccountConst.Flushes_No);
		
		List<LotCashBill> bills = lotCashBillDao.queryLotCashBill(params);
		if(bills == null || bills.size() <= 0)
			return;
		
		LotCashBill target = bills.get(0);
		Map<String, Object> billParams = new HashMap<String, Object>();
		billParams.put("billId", target.getBillId());
		billParams.put("isFlushes", AccountConst.Flushes_Yes);
		
		Map<String, Object> flushesParams = new HashMap<String, Object>();
		flushesParams.put("accountId", target.getAccountId());
		flushesParams.put("money", target.getBillExpend());
		
		flushesTransaction(billParams, flushesParams);
	}

	private void flushesTransaction(Map<String, Object> billParams,
			Map<String, Object> flushesParams) {
		lotCashBillDao.flushes(billParams);
		lotCashInfoDao.flushes(flushesParams);
	}

}
